package com.edgar.rtree;

/**
 * @Auther EdgarLQS
 * @Date 2023-09-08 16:48
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName RTree
 * @Description
 */
public class RTree
{
    public RTNode getRoot() {
        return root;
    }

    /**
     * 根节点
     */
    private RTNode root;


    /**
     * 树类型
     */
    private int tree_type;

    /**
     * 结点容量
     */
    private int nodeCapacity = -1;

    /**
     * 结点填充因子
     */
    private float fillFactor = -1;

    /**
     * 维数
     */
    private int dimension ;

    // 节点容量 结点填充因子 树类型
    public RTree(int capacity, float fillFactor, int type, int dimension) {
        this.fillFactor = fillFactor;
        tree_type = type;
        nodeCapacity = capacity;
        this.dimension = dimension;
        root = new RTDataNode(this, Constants.NULL);
    }

    /**
     * @return RTree的维度
     */
    public int getDimension()
    {
        return dimension;
    }

    public void setRoot(RTNode root)
    {
        this.root = root;
    }

    /**
     * @return 结点填充因子
     */
    public float getFillFactor()
    {
        return fillFactor;
    }

    /**
     * @return 返回结点容量
     */
    public int getNodeCapacity()
    {
        return nodeCapacity;
    }

    /**
     * @return 返回树的类型
     */
    public int getTreeType()
    {
        return tree_type;
    }

    /**
     * 向Rtree中插入Rectangle<p>
     * 1、先找到合适的叶节点 <br>
     * 2、再向此叶节点中插入<br>
     * @param rectangle
     */
    public boolean insert(Rectangle rectangle) {
        if(rectangle == null)
            throw new IllegalArgumentException("Rectangle cannot be null.");

        if(rectangle.getHigh().getDimension() != getDimension())
        {
            throw new IllegalArgumentException("Rectangle dimension different than RTree dimension.");
        }

        RTDataNode leaf = root.chooseLeaf(rectangle);

        return leaf.insert(rectangle);
    }

    /**
     * 从R树中删除Rectangle <p>
     * 1、寻找包含记录的结点--调用算法findLeaf()来定位包含此记录的叶子结点L，如果没有找到则算法终止。<br>
     * 2、删除记录--将找到的叶子结点L中的此记录删除<br>
     * 3、调用算法condenseTree<br>
     * @param rectangle
     * @return
     */
    public int delete(Rectangle rectangle) {
        if(rectangle == null)
        {
            throw new IllegalArgumentException("Rectangle cannot be null.");
        }

        if(rectangle.getHigh().getDimension() != getDimension())
        {
            throw new IllegalArgumentException("Rectangle dimension different than RTree dimension.");
        }

        RTDataNode leaf = root.findLeaf(rectangle);

        if(leaf != null)
        {
            return leaf.delete(rectangle);
        }

        return -1;
    }

    /**
     * 从给定的结点root开始遍历所有的结点
     * @param RTNode
     * @return 所有遍历的结点集合
     */
    public List<RTNode> traversePostOrder(RTNode root) {
        if(root == null)
            throw new IllegalArgumentException("Node cannot be null.");

        List<RTNode> list = new ArrayList<RTNode>();
        list.add(root);

        if(! root.isLeaf())
        {
            for(int i = 0; i < root.usedSpace; i ++)
            {
                List<RTNode> a = traversePostOrder(((RTDirNode)root).getChild(i));
                for(int j = 0; j < a.size(); j ++)
                {
                    list.add(a.get(j));
                }
            }
        }

        return list;
    }

}